<?php

namespace App\Web\Model;

use App\Facades\UrlCrypt;
use App\Service\DbIndex;
use App\Service\FileHandler;
use App\Web\Facades\UserAuth;
use EchoPHP\Facades\Db;
use EchoPHP\Validator\Validator;
use App\Web\Model\TaskDetail as TaskDetailModel;

/**
 * Class Task
 * 任务管理相关业务逻辑
 * @package App\Web\Model
 */
class Task extends Model {
    /**
     * 查询总记录数
     * @param array $search
     * @return array
     */
    public function getListCount($loginId, $search = []) {
        $field = 'count(1) as count';
        return $this->selinfo($loginId, $search, $field)[0]['count'];
    }

    /**
     * 任务表单参数校验
     * @param array $taskParams
     * @param null $attach
     * @return array
     */
    public function taskParamsValidate(array $taskParams, $attach = null) {
        $rule = [
            'taskname|任务名称' => ['required', 'minLength' => '2', 'maxLength' => '100'],
            'tasktype|任务类型' => ['required', 'in' => '01,02,03,04,05,06,07,09'],
            'startdate|开始时间' => ['required', 'dateFormat' => 'Y-m-d H:i:s', 'before' => 'enddate'],
            'enddate|结束时间' => ['required', 'dateFormat' => 'Y-m-d H:i:s'],
            'memo|任务备注' => ['maxLength' => '200'],
            'attach|任务附件' => ['file', 'minSize' => 0, 'maxSize' => 10240],
            'receiverinfo' => ['required', 'array']
        ];
        $msg = [
            'tasktype.in' => '请选择正确的任务类型',
            'attach' => '请上传10M以内附件',
            'receiverinfo' => '请选择接收人'
        ];

        $validate = new Validator($rule, $msg);
        $result = $validate->validate([
            'taskname' => $taskParams['taskname'],
            'tasktype' => $taskParams['tasktype'],
            'startdate' => $taskParams['startdate'],
            'enddate' => $taskParams['enddate'],
            'memo' => $taskParams['memo'],
            'attach' => $attach,
            'receiverinfo' => $taskParams['receiverinfo'],
        ]);
        if (!$result) {
            return ['status' => false, 'message' => '校验失败', 'errorFields' => $validate->getErrors()];
        }
        return ['status' => true, 'message' => '校验通过'];
    }

    /**
     * 任务信息新增
     * @param $param
     * @param null $attach
     * @return array
     * @throws \Throwable
     */
    public function saveTaskInfo($param, $attach = null) {
        $validateResult = $this->taskParamsValidate($param, $attach);
        if (!$validateResult['status']) {
            return $validateResult;
        }
        $oprId = UserAuth::getLoginId();
        $oprName = UserAuth::getLoginCname();

        //附件处理
        if (!is_null($attach)) {
            $fileHandler = new FileHandler($attach);
            $destination = config('app.file_task.directory');
            $targetInfo = $fileHandler->move(true, $destination);
            $attachPath = $targetInfo['relativepathname'];
            $attachName = $targetInfo['originalname'];
        } else {
            $attachPath = '';
            $attachName = '';
        }
        $result = Db::connect('jyrpo_pdo')->transaction(function () use ($param, $oprId, $oprName, $attachPath, $attachName) {

            if ($param['resumeid'] && json_decode($param['resumeid'])) {
                $sql = 'select subid from Project where projectid = ?';
                $subId = Db::selectOne($sql, [$param['projectid']]);
                if (!$subId) {
                    return false;
                }
                $subId = $subId['subid'];
                $dbIndex = DbIndex::getDbIndex($subId);
                $dbName = 'jyrpo_' . $dbIndex['dbid'];
                $where = [];
                $var = ['01'];
                $sql = 'select caseid,resumeid,flowat,flowatstatus from CaseResume_' . $dbIndex['tableid'] . ' where status = ? and';
                $param['resumeid'] = json_decode($param['resumeid'], true);

                //使用resumeid索引
                $inFlag = substr(str_repeat('? ,', (count($param['resumeid']))), 0, -1);
                $sql .= ' resumeid in ( ' . $inFlag . ' ) and ';
                $var = array_merge($var, array_column($param['resumeid'], 'resumeid'));
                foreach ($param['resumeid'] as $item) {
                    $where[] = ' (caseid = ? and resumeid = ?) ';
                    $var[] = $item['caseid'];
                    $var[] = $item['resumeid'];
                }
                $sql .= ' ( ' . implode('or', $where) . ' ) ';
                $result = Db::connect($dbName)->select($sql, $var);
                foreach ($param['resumeid'] as $key => $value) {
                    foreach ($result as $item) {
                        if ($value['resumeid'] == $item['resumeid'] && $value['caseid'] == $item['caseid']) {
                            $param['resumeid'][$key] = array_merge($value, ['flowat' => $item['flowat'], 'flowatstatus' => $item['flowatstatus']]);
                            break;
                        }
                    }
                }
                $param['resumeid'] = json_encode($param['resumeid']);
            }


            $taskInsSql = 'INSERT INTO Task(taskname,tasktype,submitter,startdate,enddate,memo,isfullday,resumeid,projectname,projectid,attachpath,attachname,createdate,updatedate,status,receivercount,submittername) values '
                . '(?,?,?,?,?,?,?,?,?,?,?,?,now(),now(),?,?,?)';
            $taskInsVar = [
                $param['taskname'], $param['tasktype'], $oprId, $param['startdate'], $param['enddate'],
                $param['memo'], $param['isfullday'], $param['resumeid'], $param['projectname'],
                $param['projectid'], $attachPath, $attachName, '01', count($param['receiverinfo']),
                $oprName,
            ];
            Db::connect('jyrpo_pdo')->insert($taskInsSql, $taskInsVar);
            $taskId = Db::connect('jyrpo_pdo')->getLastInsertId();

            $taskDetailInsSql = 'INSERT INTO TaskDetail(receiver,status,taskid,createdate,updatedate,startdate,enddate,taskname,isfullday,memo,tasktype,receivername) values ';
            $taskDetailInsVar = [];
            foreach ($param['receiverinfo'] as $key => $receiverInfo) {
                $taskDetailInsSql .= '(?,?,?,now(),now(),?,?,?,?,?,?,?),';
                $taskDetailInsVar = array_merge($taskDetailInsVar, [
                    $receiverInfo['userid'], '01', $taskId, $param['startdate'], $param['enddate'], $param['taskname'], $param['isfullday'], $param['memo'], $param['tasktype'], $receiverInfo['cname']
                ]);
            }
            $taskDetailInsSql = substr($taskDetailInsSql, 0, -1);
            $result = Db::connect('jyrpo_pdo')->insert($taskDetailInsSql, $taskDetailInsVar);
            return $result;
        });
        return ['status' => $result, 'message' => $result ? '新增成功' : '新增失败',];

    }

    /**
     * 查询我发起的任务
     * @param $search
     * @return array
     */
    public function selinfo($loginId, $search = [], $field = '', $rowFrom = 0, $rowTo = 0, $orderBy = '') {
        $field = empty($field) ? "taskid,taskname,tasktype,submitter,startdate,enddate,memo,isfullday,resumeid,projectname,projectid,attachpath,attachname,status,receivercount,submittername" : $field;
        $sql = 'SELECT ' . $field . ' FROM Task ';
        $var = [];
        $var[] = $loginId;
        $where = [];
        $where[] = 'submitter = ?';
        //查询任务名称/ID
        if (isset($search['taskname']) && !empty($search['taskname'])) {
            $nameParam = $this->searchStringOrNum($search['taskname'], 'taskname', 'taskid');
            $where[] = $nameParam['where'];
            $var = array_merge($var, $nameParam['var']);
        }
        //任务类型
        if (isset($search['tasktype']) && !empty($search['tasktype'])) {
            $where[] = 'tasktype = ?';
            $var[] = $search['tasktype'];
        }

        //任务时间
        if (isset($search['startdate']) && !empty($search['startdate'])) {
            $where[] = 'startdate >= ? ';
            $var[] = $search['startdate'] . ' 00:00:00';
        }
        if (isset($search['enddate']) && !empty($search['enddate'])) {
            $where[] = ' enddate <= ? ';
            $var[] = $search['enddate'] . ' 23:59:59';
        }

        //状态已完成，未完成
        if (isset($search['status']) && !empty($search['status'])) {
            $where[] = 'status = ?';
            $var[] = $search['status'];
        } else {
            $where[] = 'status != ?';
            $var[] = "06";
        }
        $sql .= ' WHERE ' . implode(' AND ', $where);
        $sql .= empty($orderBy) ? ' ORDER BY taskid DESC' : (' ORDER BY ' . $orderBy);
        return Db::select($sql, $var, $rowFrom, $rowTo);
    }

    /**
     * 完成任务
     * @param $oprID
     * @param $taskDetailID
     * @param string $handleType
     * @return bool
     * @throws \Throwable
     */
    public function finishInfo($oprID, $taskDetailID, $handleType = 'finish') {
        $sql = 'SELECT taskid,status,receiver FROM TaskDetail WHERE taskdetailid = ?';
        $var = [$taskDetailID];
        $taskDetailInfo = Db::connect()->selectOne($sql, $var);
        if (!$taskDetailInfo || $taskDetailInfo['receiver'] != $oprID) {
            return false;
        }
        if ($handleType == 'finish') {
            $beforeStatus = '01';
            $afterStatus = '02';
        } else {
            $beforeStatus = '02';
            $afterStatus = '01';
        }
        if ($taskDetailInfo['status'] == $afterStatus) {
            return true;
        }
        $taskID = $taskDetailInfo['taskid'];

        Db::connect('jyrpo_pdo')->transaction(function () use ($oprID, $taskID, $taskDetailID, $afterStatus, $beforeStatus) {
            $updTaskDetailSql = 'UPDATE TaskDetail SET status= ?,updatedate= Now()  WHERE taskdetailid = ? AND status= ? ';
            $updTaskDetailVar = [$afterStatus, $taskDetailID, $beforeStatus];
            Db::connect('jyrpo_pdo')->update($updTaskDetailSql, $updTaskDetailVar);

            $updTasksql = 'UPDATE Task SET status=(SELECT CASE count WHEN 0 THEN ? else ? END FROM (SELECT count(1) as count FROM TaskDetail WHERE taskid=? AND status=?) as Count),updatedate= Now()  WHERE taskid = ?';
            $updTaskVar = ['02', '01', $taskID, '01', $taskID];
            Db::connect('jyrpo_pdo')->update($updTasksql, $updTaskVar);
        });
        return true;
    }

    /**
     * 获取任务附件
     * @param $taskId
     * @return mixed
     */
    public function getTaskAttach($taskId) {
        //发起的任务
        $sql = 'select taskid,attachpath,attachname from Task where taskid=? and submitter=?';
        $var = [$taskId, UserAuth::getLoginId()];
        $resultTask = Db::selectOne($sql, $var);
        if (isset($resultTask['taskid'])) {
            return $resultTask;
        }

        //接收的任务
        $sql = 'select taskid from TaskDetail where taskid=? and receiver=?';
        $var = [$taskId, UserAuth::getLoginId()];
        $resultTask = Db::selectOne($sql, $var);

        if (!isset($resultTask['taskid'])) {
            if (UserAuth::getLoginInfo('teamrole') == 2) {
                $sql = 'select taskid from TaskDetail left join User on receiver=userid where taskid=? and teamcode like ?';
                $teamCode = UserAuth::getLoginInfo('teamcode');
                $var = [$taskId, $teamCode . '%'];
                $resultTask = Db::selectOne($sql, $var);
            }
        }

        if (!isset($resultTask['taskid'])) {
            return [];
        }

        $sql = 'select attachpath,attachname From Task where taskid = ?';
        $var = [$taskId];
        return Db::selectOne($sql, $var);
    }

    /**
     * 获取任务明细
     * @param $taskId
     * @return array
     */
    public function getTaskInfo($oprId, $taskId) {
        $return = [];
        $sql = 'select * From Task where taskid = ?';
        $var = [$taskId];
        $taskInfo = Db::selectOne($sql, $var);
        if (empty($taskInfo)) {
            return $return;
        }
        if ($taskInfo['resumeid'] && json_decode($taskInfo['resumeid'])) {
            $resumeInfo = json_decode($taskInfo['resumeid'], true);
            $sql = 'select subid from SCase where caseid = ?';
            $subId = Db::selectOne($sql, [$resumeInfo[0]['caseid']]);
            if (!$subId) {
                return false;
            }
            $subId = $subId['subid'];
            $dbIndex = DbIndex::getDbIndex($subId);
            $dbName = 'jyrpo_' . $dbIndex['dbid'];
            $where = [];
            $var = ['01'];
            $sql = 'select caseid,resumeid,flowat,flowatstatus from CaseResume_' . $dbIndex['tableid'] . ' where status = ? and';
            //使用resumeid索引
            $inFlag = substr(str_repeat('? ,', (count($resumeInfo))), 0, -1);
            $sql .= ' resumeid in ( ' . $inFlag . ' ) and ';
            $var = array_merge($var, array_column($resumeInfo, 'resumeid'));
            foreach ($resumeInfo as $item) {
                $where[] = ' (caseid = ? and resumeid = ?) ';
                $var[] = $item['caseid'];
                $var[] = $item['resumeid'];
            }
            $sql .= ' ( ' . implode('or', $where) . ' ) ';
            $result = Db::connect($dbName)->select($sql, $var);
            foreach ($resumeInfo as $key => $value) {
                foreach ($result as $item) {
                    if ($value['resumeid'] == $item['resumeid'] && $value['caseid'] == $item['caseid']) {
                        $resumeInfo[$key] = array_merge($value, ['nowflowat' => $item['flowat'], 'nowflowatstatus' => $item['flowatstatus']]);
                        break;
                    }
                }
            }
            $caseFlowModel = new CaseFlow();
            $resumeInfo = $caseFlowModel->rowTrans($resumeInfo);
            $resumeInfo = $caseFlowModel->rowTrans($resumeInfo, 'nowflowat', 'nowflowatstatus');
            $taskInfo['resumeid'] = json_encode($resumeInfo);
        }
        $return['taskinfo'] = $taskInfo;

        $sql = 'select receiver,receivername From TaskDetail where taskid = ?;';
        $var = [$taskId];
        $return['receiver'] = Db::select($sql, $var);
        $receiverIds = [];
        foreach ($return['receiver'] as $receiver) {
            $receiverIds[] = $receiver['receiver'];
        }
        $sql = 'select teamrole,teamcode from User where userid=? and status=?';
        $var = [$oprId, '01'];
        $result = Db::selectOne($sql, $var);
        $sql = 'SELECT teamcode FROM TaskDetail as t left join User as u on t.receiver=u.userid where taskid=? group by teamcode;';
        $var = [$taskId];
        $teamResult = Db::select($sql, $var);
        $teams = [];
        foreach ($teamResult as $team) {
            $teams[] = substr($team['teamcode'], 0, strlen($result['teamcode']));
        }
        //只能看自己收到的和发起的任务
        if ($oprId != $return['taskinfo']['submitter'] && !in_array($oprId, $receiverIds)) {

            if ($result['teamrole'] == 1) { //是不是团队leader
                return [];
            }
            if (!in_array($result['teamcode'], $teams)) {//是团队leader则查看该任务有没有自己的团队参与
                return [];
            }
        }
        $caseResumeIds = json_decode($taskInfo['resumeid'], true);
        if (!$caseResumeIds) {
            return $return;
        }
        $resumeIds = $caseIds = [];
        foreach ($caseResumeIds as $item) {
            $resumeIds[] = $item['resumeid'];
            $caseIds[] = $item['caseid'];
        }
        $resumeIds = array_unique($resumeIds);
        $managerModel = new Manager();
        $return['resumelist'] = $managerModel->getManagerListWithChkDownload($oprId, $resumeIds);

        $resumeidArr = array_column($resumeInfo, 'resumeid');
        $return['listkey'] = implode(",", $resumeidArr);
        $return['listtoken'] = UrlCrypt::generateToken($resumeidArr);

        $caseIds = array_unique($caseIds);
        $caseModel = new CaseModel();
        $return['caselist'] = $caseModel->getCaseList($caseIds, 'caseid,casename,subid,projectid,status');
        return $return;
    }

    public function getUnfinishedCount($oprId) {
        //我发起的任务
        $sql = 'select count(distinct taskid) as count from Task where submitter=? and status=?';
        $var = [$oprId, '01'];
        $subCount = Db::select($sql, $var)[0]['count'];
        //我收到的任务
        $sql = 'select count(distinct taskid) as count from TaskDetail where receiver=? and status=?';
        $var = [$oprId, '01'];
        $recCount = Db::select($sql, $var)[0]['count'];
        //如果是团队leader 团队下未完成任务
        $sql = 'select teamcode,teamrole from User where userid=? and status=?';
        $var = [$oprId, '01'];
        $result = Db::selectOne($sql, $var);
        if (!empty($result) && $result['teamrole'] == 2) {
            $teamCode = $result['teamcode'];
            $sql = 'select count(1) as count from TaskDetail left join User on receiver=userid where teamcode like ? and TaskDetail.status=?';
            $var = [$teamCode . '%', '01'];
            $teamCount = Db::select($sql, $var)[0]['count'];
        }
        return [
            'subcount' => $subCount,  //我发起的未完成的任务数量
            'reccount' => $recCount,  //我收到的未完成的任务数量
            'teamcount' => isset($teamCount) ? $teamCount : 0
        ];
    }

    public function endTask($oprId, $taskId) {
        $statement = [];
        if (empty($taskId)) {
            return ['status' => false, 'message' => '未选中任务'];
        }
        $taskId = explode(',', $taskId);
        $inFlag = substr(str_repeat('? ,', (count($taskId))), 0, -1);
        $sql = 'select taskid from Task where submitter=? and status=? and taskid in (' . $inFlag . ')';
        $var = array_merge([$oprId, '01'], $taskId);
        $taskList = Db::select($sql, $var);
        if (empty($taskList)) {
            return ['status' => false, 'message' => '任务不存在或已完成'];
        }
        $taskIds = [];
        foreach ($taskList as $item) {
            $taskIds[] = $item['taskid'];
        }
        $inFlag = substr(str_repeat('? ,', (count($taskIds))), 0, -1);
        $sql = 'update Task set status=?,updatedate=Now() where taskid in (' . $inFlag . ')';
        $var = array_merge(['02'], $taskIds);
        $statement[] = Db::connect()->prepareStatement($sql, $var);

        $sql = 'update TaskDetail set status=?,updatedate=Now() where taskid in (' . $inFlag . ')';
        $var = array_merge(['02'], $taskIds);
        $statement[] = Db::connect()->prepareStatement($sql, $var);
        $result = Db::connect()->prepareTransactionStatement(true, ...$statement)->execute();
        return $result ? ['status' => true, 'message' => '操作成功'] : ['status' => false, 'messsage' => '操作失败'];
    }

}